/**
 * 		-	ad-creatif	-
 * 		-	20/07/2012	-
 *
 * This class imports the game's config.xml file, cut it, verify all params
 * before storing them in the registry. It show the "pink" loading bar and display loading errors
 * 
 * 
 **/

package tools {
	import com.greensock.events.LoaderEvent;
	import com.greensock.loading.*;
	import com.greensock.loading.display.ContentDisplay;
	
	import flash.display.Sprite;
	import flash.errors.IOError;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	import org.flixel.FlxG;
	import org.flixel.FlxSound;
	import org.flixel.FlxText;
	
	public class AssetsLoader {
		
		public function AssetsLoader() { }
		
		private static var abilitiesLoader:XMLLoader;
		private static var configLoader:XMLLoader;
		private static var gameFolder:String;
		private static var queue:LoaderMax;
		
		private static var sprite:Sprite;
		
		public static function massLoader(onEndCallback:Function):void {
			
			//  I'll load tileMaps.txt, tileSheets.png, and config.xml
			//LoaderMax.activate([ImageLoader, DataLoader, XMLLoader]);
			
			//  I'm catching the template folder
			AssetsLoader.gameFolder = Registry.gameList[Registry.gameName].dirUrl;
			
			
			//  first I load the xml file : config.xml (wich is in the template folder)
			configLoader = new XMLLoader(AssetsLoader.gameFolder + 'config.xml', {name: "xmlParams", 
				onFail:errorHandler, 
				//onProgress: progressHandler, 
				onComplete: function(event:LoaderEvent):void {
					
					Registry.tileInfos = {};
					var xml:XML = configLoader.getContent('xmlParams');
					
					queue = new LoaderMax({name: 'files', onProgress : progressHandler, skipFailed : true,onComplete: function(event:LoaderEvent):void {
						
						if(FlxG.stage.getChildByName(sprite.name))FlxG.stage.removeChild(sprite);
						
						for (var key:String in Registry.tileInfos) {
							var rti:Object = Registry.tileInfos[key];
							if(rti['tileMapUrl'] && queue.getContent(rti['tileMapUrl']) )
								rti['tileMap'] = queue.getContent(rti['tileMapUrl']);
							if(rti['imgUrl'] && queue.getContent(rti['imgUrl'])['rawContent']) 
								rti['tileSheet'] = queue.getContent(rti['imgUrl'])['rawContent']['bitmapData'];
						}
						for ( key in Registry.entityInfos){
							var rei:Object = Registry.entityInfos[key].tile
							if(rei['imgUrl']) rei['tileSheet'] = queue.getContent(rei['imgUrl'])['rawContent']['bitmapData'];
							rei['sounds'] = queue.getContent
							for( var sound:String in Registry.entityInfos[key].sounds ) Registry.entityInfos[key].sounds[sound] = queue.getContent(sound);
						}
						
						for ( key in Registry.blockInfos){
							var rbi:Object = Registry.blockInfos[key];
							if(rbi['imgUrl']) rbi['image'] = queue.getContent(rbi['imgUrl'])['rawContent']['bitmapData'];
						}
						
						for ( key in Registry.weaponInfos){
							var rwi:Object = Registry.weaponInfos[key];
							rwi['image'] = queue.getContent(rwi['imgUrl'])['rawContent']['bitmapData'];
						}
						for ( key in Registry.attacks){
							var ra:Object = Registry.attacks[key];
							if( queue.getContent(ra['imgUrl']) )
								ra['image'] = queue.getContent(ra['imgUrl'])['rawContent']['bitmapData'];
						}
						
						
						if(queue.getContent(Registry.gameInfos.template['btnImgUrl']))
							Registry.gameInfos.template['btnImg'] = LoaderMax.getContent(Registry.gameInfos.template['btnImgUrl'])['rawContent']['bitmapData'];
						
						if(queue.getContent(Registry.gameInfos.template['btnHoverImgUrl']))
							Registry.gameInfos.template['btnHoverImg'] = LoaderMax.getContent(Registry.gameInfos.template['btnHoverImgUrl'])['rawContent']['bitmapData'];
						
						if (queue.getContent(Registry.gameInfos.template['logoUrl'])) 
							Registry.gameInfos.template['logo'] = LoaderMax.getContent(Registry.gameInfos.template['logoUrl'])['rawContent']['bitmapData'];
						
						if (queue.getContent(Registry.gameInfos.hud['imgUrl'])) 
							Registry.gameInfos.hud['image'] = LoaderMax.getContent(Registry.gameInfos.hud['imgUrl'])['rawContent']['bitmapData'];
							
						
						onEndCallback();
					}
					});
					
					fillRegistry(xml);
					queue.prependURLs(gameFolder);
					queue.load();
					
				} // end of xml loader
			});
			configLoader.load();
		}
		
		
		private static function fillRegistry(xml:XML):void{
			
			
			
			/**********************************		TILES		**********************************/
			for (var i:int = 0; i < xml.parameters.tileInfos.children().length(); i++) {
				// get xml part
				var ti:XML = xml.parameters.tileInfos.children()[i];
			
				Registry.tileInfos[ti.@name] = {
					'name':  checkString(ti.@name), 
					'type' :  checkString(ti.@type),
					'tileMapUrl': checkString(ti.@tileMapUrl), 
					'tileSize': checkNumber(ti.@tileSize),
					'imgUrl': checkString(ti.@imgUrl), 
					'scrollFactor': parseFloat(ti.@scrollFactor)
				};
				
				if (ti.@tileMapUrl != ti.@azerty) queue.append(new DataLoader(ti.@tileMapUrl, {'name': ti.@tileMapUrl}));
				if (ti.@imgUrl != ti.@azerty || ti.@type != 'enemy' ) queue.append(new ImageLoader(ti.@imgUrl, {'name': ti.@imgUrl}));
				
			}
			
			
			
			
			/**********************************		ENTITIES		**********************************/
			Registry.entityInfos = {};
			
			for (i = 0; i < xml.parameters.entityInfos.children().length(); i++) {
				
				var ei:XML = xml.parameters.entityInfos.children()[i];
				
				if (ei.tile.@imgUrl !=  ei.@azerty) queue.append(new ImageLoader(ei.tile.@imgUrl, {'name': ei.tile.@imgUrl}));
				
				Registry.entityInfos[ei.@name] = { //
					'name': checkString(ei.@name),
					'type' : checkString(ei.@type),
					'tile': {
						'imgUrl': checkString(ei.tile.@imgUrl),
						'tileSize': checkNumber( ei.tile.@tileSize), 
						'offset': checkNumber(ei.tile.@offset),  
						'realSize' : checkNumber(ei.tile.@realSize), 
						'tileID': checkNumber(ei.tile.@tileID)
					}, //
					'anims': {}, //
					'sounds': {}, //
					'gamePlay': {
						'speed': checkNumber(ei.gamePlay.@speed),
						'jumpHeight': checkNumber(ei.gamePlay.@jumpHeight),
						'health': checkNumber(ei.gamePlay.@health), 
						'lives': checkNumber(ei.gamePlay.@lives), 
						'acceleration': checkNumber(ei.gamePlay.@acceleration), 
						'deceleration': checkNumber(ei.gamePlay.@deceleration),
						'points' : checkNumber(ei.gamePlay.@points),
						'tracking' : (ei.gamePlay.@tracking ==  'true') ? true:false,
						'charging' : (ei.gamePlay.@charging ==  'true') ? true:false,
						'jumping' : (ei.gamePlay.@jumping ==  'true') ? true:false,
						'stayOnPlatform' : (ei.gamePlay.@stayOnPlatform ==  'true') ? true:false,
						'destroyWall' : (ei.gamePlay.@destroyWall ==  'true') ? true:false
					}, //
					'attack': {
						'meleeDamage': checkNumber(ei.attack.@meleeDamage) ,
						'weaponsName': checkString(ei.attack.@weapons, true),
						'weaponOffset': checkNumber(ei.attack.@weaponOffset)
					}
				};
				
				//store anims
				for each ( var anim:XML in ei.anims.attributes() ){
					var animName:String = anim.name();
					Registry.entityInfos[ei.@name]['anims'][animName] = checkNumber(anim,true);
				}
				//store sounds
				for each ( var sound:XML in ei.sounds.attributes() ){
					var soundName:String = sound.name();
					Registry.entityInfos[ei.@name]['sounds'][soundName] = {};
					queue.append(new MP3Loader(sound, {'name': soundName, autoPlay : false}));
				}
			}

			
			
			
			
			
			/**********************************		BLOCS		 **********************************/
			Registry.blockInfos = {};
			for (i = 0; i < xml.parameters.blockInfos.children().length(); i++) {
				// get xml part
				var bi:XML = xml.parameters.blockInfos.children()[i];
				
				if (bi.@imgUrl !=  bi.@azerty) queue.append(new ImageLoader(bi.@imgUrl, {'name': bi.@imgUrl}));
				
				Registry.blockInfos[bi.@name] = {
					'name': checkString(bi.@name), 
					'type': checkString(bi.@type), 
					'tileID': checkNumber(bi.@tileID,true), 
					'bonusType' : checkString(bi.@bonusType),
					'firstTileID': checkNumber(bi.@firstTileID), 
					'newTileID': checkNumber(bi.@newTileID), 
					'description' : checkString(bi.@description),
					'points': checkNumber(bi.@points), 
					'url': checkString(bi.@linkUrl), 
					//'imgUrl' : checkString(bi.@imgUrl),
					'soundUrl': checkSound(bi.@soundUrl), 
					'damages': checkNumber(bi.@damages),
					'collide': (bi.@collide == 'false')? false:true,
					'range': checkNumber(bi.@range),
					'timer': checkNumber(bi.@timer),
					'speed' : checkNumber(bi.@speed),
					'triggerName' : checkString(bi.@triggerName)
				};
			}

			
			
			/**********************************		WEAPONS		 **********************************/
			Registry.weaponInfos = {};
			
			for (i = 0; i < xml.parameters.weaponInfos.children().length(); i++) {
				// get xml part
				var wi:XML = xml.parameters.weaponInfos.children()[i];
				
				
				Registry.weaponInfos[wi.@name] = {
					'name': checkString(wi.@name), 
					'sound': checkSound(wi.@soundUrl), 
					'imgUrl': checkString(wi.@imgUrl),
					'speed': checkNumber(wi.@speed), 
					'delay': checkNumber(wi.@delay), 
					'power': checkNumber(wi.@power), 
					'gravity': checkNumber(wi.@gravity), 
					'frames': checkNumber(wi.@frames,true)
				};
				if (Registry.weaponInfos[wi.@name].imgUrl !=  wi.@azerty) queue.append(new ImageLoader(Registry.weaponInfos[wi.@name].imgUrl, {'name': Registry.weaponInfos[wi.@name].imgUrl}));
				
			}
			
			
			
			/**********************************		ATTACKS		**********************************/
			Registry.attacks = {};
			
			for (i = 0; i < xml.parameters.attacks.children().length(); i++) {
				var at:XML = xml.parameters.attacks.children()[i];
				
				if (at.@imgUrl !=  at.@azerty) queue.append(new ImageLoader(at.@imgUrl, {'name': at.@imgUrl}));
				
				Registry.attacks[at.@attackName] = {
					'duration' : checkNumber( at.@duration ),
					'sound' : checkSound( at.@soundUrl ),
					'imgUrl' : checkString( at.@imgUrl ),
					'size' : checkNumber( at.@size ),
					'minionName' : checkString( at.@minionName ),
					'damages' : checkNumber( at.@damages ),
					'speedFactor' : checkNumber(at.@speedFactor),
					'quantity' :checkNumber( at.@quantity )
				}
			}
			
			
				
			
			/**********************************		ABILITIES	**********************************/
			Registry.abilities = {};
				
			for (i = 0; i < xml.parameters.abilities.children().length(); i++) {
				var ab:XML = xml.parameters.abilities.children()[i];
				
				Registry.abilities[ab.@name] = {};
				if(Registry.entityInfos[ab.@name])
					Registry.entityInfos[ab.@name].gamePlay['healthMode'] = (ab.@healthMode ==  'true') ? true:false;
				else trace('assignation de capacité à une unité inexistante');
				
				for (var j:int = 0 ; j < ab.children().length() ; j++){
					
					var aii:XML = ab.children()[j];
					
					Registry.abilities[ab.@name][aii.@level] = {
						'level' : checkNumber(aii.@level),
						'attackName' : checkString(aii.@attackName,true),
						'trigger': checkNumber(aii.@trigger),
						'coolDown': checkNumber(aii.@coolDown)
					}
				}
			}
			
			
			
			
			
			/**********************************		OTHERS OPTIONS		 **********************************/
			var g:XMLList = xml.game;
			Registry.gameInfos = {};
			
			
			Registry.gameInfos['debugMode'] = (checkString(g.@debugMode) != "true") ? false : true;
			
			Registry.gameInfos['world'] = {
				'prevLevel' : checkString(g.world.@prevLevel),
				'nextLevel' : checkString(g.world.@nextLevel),
				'crossingTiles' : checkNumber(g.world.@crossingTiles,true),
				'startPos' : checkNumber(g.world.@startPos),
				'gravity' : !checkNumber(g.world.@gravity) ? 0 : checkNumber(g.world.@gravity),
				'music' : checkSound(g.template.@musicUrl)
			};
			Registry.gameInfos['template'] = {
				'backgroundColor' : checkString(g.template.@backgroundColor),
				'fontFamily' : checkString(g.template.@fontFamily),
				'fontSize' : checkNumber(g.template.@fontSize),
				'fontColor' : checkString(g.template.@fontColor),
				'btnImgUrl' : checkString(g.template.@btnImgUrl),
				'btnHoverImgUrl' : checkString(g.template.@btnHoverImgUrl),
				'btnSize' : checkNumber(g.template.@btnSize),
				'logoUrl' : checkString(g.template.@logoUrl)
			};
			Registry.gameInfos['hud'] = {
				'imgUrl' : checkString(g.hud.@imgUrl),
				'hudPos' : checkNumber(g.hud.@hudPos),
				'hudHeight' : checkNumber(g.hud.@hudHeight),
				'healthbarPos' : checkNumber(g.hud.@healthbarPos),
				'healthbarSize' : checkNumber(g.hud.@healthbarSize),
				'healthbarColor' : checkString(g.hud.@healthbarColor),
				'scorePos' : checkNumber(g.hud.@scorePos)
			};

			//store controls
			Registry.gameInfos.controls =  {};
			for each (var control:XML in g.controls.attributes() ){
				var controlName:String = control.name();
				Registry.gameInfos.controls[controlName] = checkString(control);
			}
			
			if (Registry.gameInfos.template['btnImgUrl']) queue.append(new ImageLoader(Registry.gameInfos.template['btnImgUrl'], {'name' : Registry.gameInfos.template['btnImgUrl']}));
			if (Registry.gameInfos.template['btnHoverImgUrl']) queue.append(new ImageLoader(Registry.gameInfos.template['btnHoverImgUrl'], {'name' : Registry.gameInfos.template['btnHoverImgUrl']}));
			if (Registry.gameInfos.template['logoUrl']) queue.append(new ImageLoader(Registry.gameInfos.template['logoUrl'], {'name': Registry.gameInfos.template['logoUrl']}));
			if (Registry.gameInfos.hud['imgUrl']) queue.append(new ImageLoader(Registry.gameInfos.hud['imgUrl'], {'name': Registry.gameInfos.hud['imgUrl']}));
			
			
			
			
			/********************************** CHECKING FUNCTIONS **********************************/
			// returns null if the attribute doesn't exist and eventually split arrays
			function checkNumber(number:*, returnArray:Boolean = false):*{
				
				if(number == xml.@azerty) return null;
				
				var tempArray:Array =  String(number).split(',');
				if (tempArray.length == 1 && !returnArray) return Number(tempArray[0]);
				else {
					for(var id:String in tempArray){
						if	(tempArray[id]== xml.@azerty) tempArray[id] = null;
						else tempArray[id] =  Number(tempArray[id]);
					}
					return tempArray;
				}
			}
			
			//returns null if the attribute doesn't exist and eventually split arrays
			function checkString(string:*, returnArray:Boolean = false):*{
				if(string == xml.@azerty) return null;
				var tempArray:Array =  String(string).split(',');
				if (tempArray.length == 1 && !returnArray) return tempArray[0];
				else return tempArray;
			}
			
			// returns null if the sound url isn't given
			function checkSound(url:XMLList):*{
				if(url  == xml.@azerty) return null;
				
				var sound:FlxSound = new FlxSound;
				sound.volume = .5;
				sound.stop();
				
				try{
					sound.loadStream(gameFolder + String(url));
				} catch(e:Error) {
					trace('son introuvable', e.message, String(url));
					return null;
				}
				return sound;
			}

		}
		
		
		// those events functions check the status of the loading
		private static function loadingFailure(e:LoaderEvent):void{trace('failure : ',e.target.name );}
		private static function childFail(e:Event):void{trace('childFail :' , e.target.name);}
		private static var percent:FlxText = new FlxText(0,0,200);
		public static function progressHandler(e:LoaderEvent):void {
			if (!sprite) {
				sprite = new Sprite();
				FlxG.stage.addChild(sprite);
			}
			sprite.graphics.clear();
			sprite.graphics.beginFill(0xff55ff, 1.0);
			sprite.graphics.drawRect(0, 10, e.target.progress * FlxG.width, 10);
			sprite.graphics.endFill();
			//trace(e.target.progress * 100, '%');
		}
		public static function errorHandler(e:LoaderEvent):void { trace("error occured with " + e.target.name + ": " + e.text); }
		
	}
}
